home *** CD-ROM | disk | FTP | other *** search
- /* unix/ui.c
- vi:ts=3 sw=3:
- */
-
- /* special termio discipline for sun/sgi,
- * for non blocking io and such.
- * These functions should not be too difficult
- * to write for a PC.
- */
- /* $Id: ui.c,v 4.4 1995/02/08 13:47:35 espie Exp espie $
- * $Log: ui.c,v $
- * Revision 4.4 1995/02/08 13:47:35 espie
- * *** empty log message ***
- *
- * Revision 4.3 1995/01/28 09:56:53 espie
- * Port to FreeBSD/NeXTstep.
- *
- * Revision 4.2 1995/01/28 09:23:38 espie
- * Support for old bsd io discipline (NeXT)
- *
- *
- * Revision 4.0 1994/01/11 18:02:31 espie
- * Major change: lots of new calls.
- * Stupid termio bug: shouldn't restore term to sanity if we don't
- * know what sanity is. For instance, if we haven't modified anything.
- * cflags interpreted correctly.
- * Hsavolai fix.
- * Added bg/fg test.
- */
-
- #ifdef dec
- #define stub_only
- #endif
-
- #ifdef __NeXT__
- #include <libc.h>
- #else /* __NeXT__ */
- #if defined(linux) || defined(__FreeBSD__)
- #include <termios.h>
- #else
- #ifdef __hpux
- #include <sys/bsdtty.h>
- #endif
- #include <sys/termio.h>
- #endif
- #ifdef __FreeBSD__
- #include <sys/ioctl.h>
- #define termio termios /* hack to not touch many places */
- #endif
- #include <signal.h>
- #endif /* __NeXT__ */
- #include "defs.h"
- #include "extern.h"
- #include "tags.h"
- #include "prefs.h"
-
-
- LOCAL void nonblocking_io P((void));
- LOCAL void sane_tty P((void));
-
- LOCAL void (*INIT)P((void)) = nonblocking_io;
-
-
- LOCAL int show;
- /* poor man's timer */
- LOCAL int current_pattern;
- LOCAL int count_pattern, count_song;
- #define SMALL_DELAY 25
-
- /* do not define any stdio routines if it's known not to work */
-
- #ifdef stub_only
-
- int run_in_fg()
- {
- return TRUE;
- }
-
- LOCAL void sane_tty()
- {
- }
-
- LOCAL struct tag end_marker;
-
- struct tag *get_ui()
- {
- end_marker.type = TAG_END;
- return &end_marker;
- }
-
- #else
-
- #ifdef __NeXT__
- LOCAL struct sgttyb sanity;
- LOCAL struct sgttyb *psanity = 0;
- #else
- LOCAL struct termio sanity;
- LOCAL struct termio *psanity = 0;
- #endif
-
- LOCAL int is_fg;
-
- /* signal handler */
-
- LOCAL void goodbye(sig)
- int sig;
- {
- static char buffer[25];
-
- sprintf(buffer, "Signal %d", sig);
- end_all(buffer);
- }
-
- LOCAL void abort_this(sig)
- int sig;
- {
- end_all("Abort");
- }
-
- #ifdef SIGTSTP
- LOCAL void suspend(sig)
- int sig;
- {
- fflush(stdout);
- sane_tty();
- signal(SIGTSTP, SIG_DFL);
- kill(0, SIGTSTP);
- }
- #endif
-
- int run_in_fg()
- {
- int val;
-
- #ifdef __hpux
- if (!isatty(fileno(stdin)) || !isatty(fileno(stdout)))
- return FALSE;
- #endif
-
- /* real check for running in foreground */
- if (ioctl(fileno(stdin), TIOCGPGRP, &val))
- return FALSE;
- #ifdef __POSIX_SOURCE
- if (val == getpgrp())
- #else
- if (val == getpgrp(0))
- #endif
- return TRUE;
- else
- return FALSE;
- }
-
- /* if_fg_sane_tty():
- * restore tty modes, _only_ if running in foreground
- */
- LOCAL void if_fg_sane_tty()
- {
- if (run_in_fg())
- sane_tty();
- }
-
-
- LOCAL void switch_mode()
- {
- #ifdef __NeXT__
- struct sgttyb zap;
- int tty;
- #else
- struct termio zap;
- #endif
-
- #ifdef SIGTSTP
- signal(SIGTSTP, suspend);
- #endif
- signal(SIGCONT, switch_mode);
- signal(SIGINT, goodbye);
- signal(SIGQUIT, goodbye);
- signal(SIGUSR1, abort_this);
-
- if (run_in_fg())
- {
- #ifdef __NeXT__
- tty = fileno(stdin);
- fcntl(tty, F_SETFL, fcntl(tty, F_GETFL, 0) | FNDELAY);
- ioctl(tty, TIOCGETP, &zap);
- zap.sg_flags |= CBREAK;
- zap.sg_flags &= ~ECHO;
- ioctl(tty, TIOCSETP, &zap);
- #else /* __NeXT__ */
- #ifdef __FreeBSD__
- tcgetattr(fileno(stdin), &zap);
- #else
- ioctl(fileno(stdin), TCGETA, &zap);
- #endif
- #ifdef linux
- zap.c_cc[VMIN] = 0;
- zap.c_cc[VTIME] = 0;
- /* Commented out
- As Hannu said:
- The current Linux kernel interprets correctly the c_lflags field so it
- should be set like for the other systems.
- zap.c_lflag = 0;
- */
- #else
- #ifdef __FreeBSD__
- zap.c_cc[VMIN] = 0; /* can't work with old */
- zap.c_cc[VTIME] = 0; /* FreeBSD versions */
- zap.c_lflag &= ~(ICANON|ECHO|ECHONL);
- #endif
- zap.c_cc[VEOL] = 0;
- zap.c_cc[VEOF] = 0;
- #endif
- zap.c_lflag &= ~(ICANON | ECHO);
- #ifdef __FreeBSD__
- tcsetattr(fileno(stdin), TCSADRAIN, &zap);
- #else
- ioctl(fileno(stdin), TCSETA, &zap);
- #endif
- #endif /* __NeXT__ */
- is_fg = TRUE;
- }
- else
- is_fg = FALSE;
- }
-
- /* nonblocking_io():
- * try to setup the keyboard to non blocking io
- */
- LOCAL void nonblocking_io()
- {
- show = get_pref_scalar(PREF_SHOW);
-
-
- #if 0 /* BROKEN */
- /* try to renice our own process to get more cpu time */
- if (nice(-15) == -1)
- nice(0);
- #endif
- if (!psanity)
- {
- psanity = &sanity;
- #ifdef __NeXT__
- ioctl(fileno(stdin), TIOCGETP, psanity);
- #else /* __NeXT__ */
- #ifdef __FreeBSD__
- tcgetattr(fileno(stdin), psanity);
- #else
- ioctl(fileno(stdin), TCGETA, psanity);
- #endif
- #endif /* __NeXT__ */
- }
- switch_mode();
- at_end(if_fg_sane_tty);
- }
-
-
- /* sane_tty():
- * restores everything to a sane state before returning to shell */
- LOCAL void sane_tty()
- {
- #ifdef __NeXT__
- ioctl(fileno(stdin), TIOCSETP, psanity);
- #else /* __NeXT__ */
- #ifdef __FreeBSD__
- tcsetattr(fileno(stdin), TCSADRAIN, psanity);
- #else
- ioctl(fileno(stdin), TCSETA, psanity);
- #endif
- #endif /* __NeXT__ */
- }
-
- LOCAL int may_getchar()
- {
- char buffer;
-
- INIT_ONCE;
-
- if (run_in_fg() && !is_fg)
- switch_mode();
- if (run_in_fg() && read(fileno(stdin), &buffer, 1))
- return buffer;
- return EOF;
- }
-
- LOCAL struct tag result[2];
-
- struct tag *get_ui()
- {
- result[0].type = TAG_END;
- result[1].type = TAG_END;
- count_pattern++;
- count_song++;
- switch(may_getchar())
- {
- case 'n':
- result[0].type = UI_NEXT_SONG;
- break;
- case 'p':
- if (count_song > SMALL_DELAY)
- result[0].type = UI_RESTART;
- else
- result[0].type = UI_PREVIOUS_SONG;
- count_song = 0;
- break;
- case 'x':
- case 'e':
- case 'q':
- result[0].type = UI_QUIT;
- break;
- case 's':
- result[0].type = UI_SET_BPM;
- result[0].data.scalar = 50;
- break;
- case 'S':
- result[0].type = UI_SET_BPM;
- result[0].data.scalar = 60;
- break;
- case '>':
- result[0].type = UI_JUMP_TO_PATTERN;
- result[0].data.scalar = current_pattern + 1;
- break;
- case '<':
- result[0].type = UI_JUMP_TO_PATTERN;
- result[0].data.scalar = current_pattern;
- if (count_pattern < SMALL_DELAY)
- result[0].data.scalar--;
- break;
- case '?':
- show = !show;
- set_pref_scalar(PREF_SHOW, show);
- if (show)
- putchar('\n');
- break;
- default:
- break;
- }
- return result;
- }
-
-
- #endif
-
-
- void notice(s)
- char *s;
- {
- fprintf(stderr, "%s\n", s);
- }
-
- void status(s)
- char *s;
- {
- if (run_in_fg())
- {
- if (s)
- {
- puts(s);
- }
- else
- putchar('\n');
- }
- }
-
- LOCAL char title[25];
- void song_title(s)
- char *s;
- {
- strncpy(title, s, 25);
- if (run_in_fg() && !show)
- puts(title);
- count_song = 0;
- }
-
-
- LOCAL char scroll_buffer[120];
-
- GENERIC begin_info(title)
- char *title;
- {
- if (run_in_fg())
- return scroll_buffer;
- else
- return 0;
- }
-
- void infos(handle, s)
- GENERIC handle;
- char *s;
- {
- if (handle)
- printf(s);
- }
-
- void info(handle, line)
- GENERIC handle;
- char *line;
- {
- if (handle)
- puts(line);
- }
-
- void end_info(handle)
- GENERIC handle;
- {
- if (handle)
- fflush(stdout);
- }
-
- LOCAL char *last_result = 0;
-
- char *new_scroll(void)
- {
- if (run_in_fg())
- {
- last_result = scroll_buffer;
- if (get_pref_scalar(PREF_COLOR))
- strcpy(scroll_buffer, " \033[0;39m\
- | \033[0;39m\
- || \033[0;39m\
- | \033[0;39m");
- else
- strcpy(scroll_buffer, " | || | ");
-
- }
- else
- last_result = 0;
- return last_result;
- }
-
- void scroll()
- {
- if (run_in_fg() && last_result)
- {
- puts(scroll_buffer);
- fflush(stdout);
- }
- }
-
- void display_pattern(current, total, real)
- int current, total, real;
- {
- if (run_in_fg())
- {
- if (show)
- printf("\n%3d/%3d[%3d] %s\n", current, total, real, title);
- else
- printf("%3d/%3d\b\b\b\b\b\b\b", current, total);
- fflush(stdout);
- }
- current_pattern = current;
- count_pattern = 0;
- }
-
- int checkbrk()
- {
- return FALSE;
- }
-